home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
html_access.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-03
|
7KB
|
298 lines
/* #Specification: html mode / access limitation
We can specify the network or host which are allowed to access linuxconf
in web mode. We can simply define a set of network and netmask pairs.
*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "../misc/misc.h"
#include "../dialog/dialog.h"
#include "internal.h"
#include "netconf.h"
#include "netconf.m"
static NETCONF_HELP_FILE help_access ("html_access");
class HTML_ACCESS: public ARRAY_OBJ{
public:
SSTRING net;
SSTRING mask;
unsigned long badr;
unsigned long bmask;
int err; // Is this entry is valid (usable)
/*~PROTOBEG~ HTML_ACCESS */
public:
HTML_ACCESS (const char *_net, const char *_mask);
/*~PROTOEND~ HTML_ACCESS */
};
PUBLIC HTML_ACCESS::HTML_ACCESS(const char *_net, const char *_mask)
{
net.setfrom (_net);
mask.setfrom (_mask);
err = 0;
badr = bmask = 0;
}
class HTML_ACCESS_TB: public ARRAY{
/*~PROTOBEG~ HTML_ACCESS_TB */
public:
HTML_ACCESS_TB (void);
private:
void addfield (DIALOG&dia, HTML_ACCESS *a);
void addfields (DIALOG&dia);
public:
int check (unsigned long badr);
int compute (char *errmsg);
void edit (void);
HTML_ACCESS *getitem (int no);
void setdefaults (void);
void write (void);
/*~PROTOEND~ HTML_ACCESS_TB */
};
static const char HTMLACCESS[]="htmlaccess";
static const char FROM[]="from";
PUBLIC HTML_ACCESS_TB::HTML_ACCESS_TB()
{
SSTRINGS tb;
int n = linuxconf_getall (HTMLACCESS,FROM,tb,0);
for (int i=0; i<n; i++){
SSTRING *s = tb.getitem(i);
char net[200];
char mask[200];
mask[0] = '\0';
sscanf (s->get(),"%s %s",net,mask);
add (new HTML_ACCESS(net,mask));
}
}
PUBLIC HTML_ACCESS *HTML_ACCESS_TB::getitem(int no)
{
return (HTML_ACCESS *)ARRAY::getitem(no);
}
PUBLIC void HTML_ACCESS_TB::write()
{
int n=getnb();
linuxconf_removeall(HTMLACCESS,FROM);
for (int i=0; i<n; i++){
HTML_ACCESS *a = getitem(i);
if (!a->net.is_empty()){
char buf[400];
sprintf (buf,"%s %s",a->net.get(),a->mask.get());
linuxconf_add (HTMLACCESS,FROM,buf);
}
}
linuxconf_save();
}
/*
Add one network to the dialog
*/
PRIVATE void HTML_ACCESS_TB::addfield(DIALOG &dia, HTML_ACCESS *a)
{
dia.newf_str (MSG_U(F_NETWORKHOST,"network or host"),a->net);
dia.newf_str (MSG_U(F_NETMASKOPT,"netmask(opt)"),a->mask);
}
/*
Add two empty networks to the dialog
*/
PRIVATE void HTML_ACCESS_TB::addfields(DIALOG &dia)
{
for (int i=0; i<2; i++){
HTML_ACCESS *a = new HTML_ACCESS ("","");
add (a);
addfield (dia,a);
}
}
static HTML_ACCESS_TB *lookup; // Use to speed up html_access_check
// avoiding reloading the struct all
// the time.
PUBLIC void HTML_ACCESS_TB::edit()
{
DIALOG dia;
/* #Specification: html access / dialog / add button
The add button simply add few more empty lines at the
end of the dialog
*/
int n=getnb();
for (int i=0; i<n; i++){
HTML_ACCESS *a = getitem(i);
addfield (dia,a);
}
addfields(dia);
dia.addwhat (MSG_U(F_EMPTYSLOT,"empty slots at the end of the dialog"));
int nof = 0;
while (1){
MENU_STATUS code = dia.edit (
MSG_U(T_HTMLACCESS,"Linuxconf html access control")
,MSG_U(I_HTMLACCESS
,"You can specify which networks or hosts are allowed\n"
"to access linuxconf to configure your computer\n"
"(They need a password still)\n")
,help_access
,nof
,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_ADD);
char errmsg[10000];
if (code == MENU_CANCEL || code == MENU_ESCAPE){
break;
}else if (code == MENU_ADD){
addfields(dia);
}else if (compute(errmsg)==-1){
xconf_error ("%s",errmsg);
}else{
delete lookup;
lookup = NULL;
write();
break;
}
}
}
void html_access_edit()
{
HTML_ACCESS_TB htb;
htb.edit ();
}
/*
To speed up peer lookup, we walk the list of hosts/networks allowed
and resolved the addresses and netmask
This function is also used to validate the dialog inputs.
Return -1 if any error in the data.
*/
PUBLIC int HTML_ACCESS_TB::compute(char *errmsg)
{
errmsg[0] = '\0';
int ret = 0;
int n = getnb();
for (int i=0; i<n; i++){
HTML_ACCESS *a = getitem(i);
a->err = 0;
const char *net = a->net.get();
if (net[0] != '\0'){
/* #Specification: html access / host or net spec
We can use the following things to specify a network or
host access. A default suitable netmask is computed
and is used unless one is supplied in the dialog.
#
-An IP number
-A host name
-A network name
-A device name (eth0). In this case the spec will be
extracted
#
*/
char ipstr[16],mskstr[16];
if (ipfwrule_convert (net,ipstr,mskstr)==-1){
ret = -1;
a->err = 1;
errmsg += sprintf (errmsg
,MSG_U(E_IVLDHOSTNET,"invalid host or network: %s\n")
,net);
}else{
int n[4];
device_aip24(ipstr,n);
a->badr = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
const char *msk = a->mask.get();
if (msk[0] == '\0') msk = mskstr;
if (device_aip24(msk,n)!=-1){
a->bmask = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
}else{
ret = -1;
a->err = 1;
errmsg += sprintf (errmsg
,MSG_U(E_IVLDMASK,"invalid netmask: %s\n")
,msk);
}
}
/* #Specification: html access / using a host to spec a net
One can use a host to specify a network by using the
proper netmask. This allows one to say "I accept all
machine of the same network as this one".
*/
a->badr &= a->bmask;
}
}
return ret;
}
/*
Tell if one host address is acceptable (in this list)
Return -1 if not
*/
PUBLIC int HTML_ACCESS_TB::check(unsigned long badr)
{
int ret = -1;
int n = getnb();
for (int i=0; i<n; i++){
HTML_ACCESS *a = getitem(i);
if (!a->err){
if (a->badr==(badr & a->bmask)){
ret = 0;
}
}
}
return ret;
}
/*
Record default rules when noone are defined
See the spec at the top of this file
*/
PUBLIC void HTML_ACCESS_TB::setdefaults()
{
/* #Specification: html mode / access limitation / default rule
The default behavior is to accept connection originating from
the eth0 network only and the localhost.
Once one rule is entered, the default is gone, even the loopback won't
be accepted.
*/
if (getnb()==0){
// Set the default behavior
add (new HTML_ACCESS("127.0.0.1","255.255.255.255"));
HOSTINFO info;
if (netconf_loadinfos(info)!=-1){
const char *ipadr = info.a[0].ipaddr.get();
char stdmask[16];
const char *mask = info.a[0].netmask.get();
if (mask[0] == '\0'){
mask = stdmask;
char stdnet[16];
device_setstdnetmask(ipadr,stdnet,stdmask);
}
add (new HTML_ACCESS(ipadr,mask));
}
}
}
/*
Check if a socket connection is coming from an accepted host
Return 0 if the "client" is allowed, -1 if not.
*/
int html_access_check (int fd)
{
int ret = -1;
struct sockaddr_in adr;
int len = sizeof(adr);
if (getpeername (fd,(struct sockaddr*)&adr,&len) != -1){
if (lookup == NULL){
lookup = new HTML_ACCESS_TB;
lookup->setdefaults();
char errmsg[10000];
lookup->compute(errmsg);
}
ret = lookup->check(ntohl(adr.sin_addr.s_addr));
}
return ret;
}